<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="robots" content="noodp" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
        <title>Mybatis加载流程分析(三) - 加载mybatis-config.xml内容 | Janyd Blog</title>
        <meta name="Description" content="Janyd Blog"><meta property="og:title" content="Mybatis加载流程分析(三) - 加载mybatis-config.xml内容" />
<meta property="og:description" content="动态配置加载propertiesElement Mybatis中的动态配置指的是上篇${}占位符替换，而这些变量来自于mybatis-conf" />
<meta property="og:type" content="article" />
<meta property="og:url" content="http://example.org/mybatis%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90%E4%B8%89-%E5%8A%A0%E8%BD%BDmybatis-config.xml%E5%86%85%E5%AE%B9/" />
<meta property="article:published_time" content="2020-04-26T14:48:30+08:00" />
<meta property="article:modified_time" content="2020-04-26T14:48:30+08:00" />
<meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="Mybatis加载流程分析(三) - 加载mybatis-config.xml内容"/>
<meta name="twitter:description" content="动态配置加载propertiesElement Mybatis中的动态配置指的是上篇${}占位符替换，而这些变量来自于mybatis-conf"/>
<meta name="theme-color" content="#ffffff">
<meta name="msapplication-TileColor" content="#da532c">
<link rel="canonical" href="http://example.org/mybatis%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90%E4%B8%89-%E5%8A%A0%E8%BD%BDmybatis-config.xml%E5%86%85%E5%AE%B9/" />
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5"><link rel="prev" href="http://example.org/mybatis%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90%E4%BA%8C-mybatis-config%E8%A7%A3%E6%9E%90/" /><link rel="next" href="http://example.org/dubbo-%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E4%B8%80-%E9%85%8D%E7%BD%AE/" /><link rel="stylesheet" href="/lib/fontawesome-free/all.min.css"><link rel="stylesheet" href="/lib/animate/animate.min.css"><link rel="stylesheet" href="/css/style.min.css"><script type="application/ld+json">
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "Mybatis加载流程分析(三) - 加载mybatis-config.xml内容",
        "inLanguage": "zh-CN",
        "mainEntityOfPage": {
            "@type": "WebPage",
            "@id": "http:\/\/example.org\/mybatis%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90%E4%B8%89-%E5%8A%A0%E8%BD%BDmybatis-config.xml%E5%86%85%E5%AE%B9\/"
        },"image": {
                "@type": "ImageObject",
                "url": "http:\/\/example.org\/cover.png",
                "width":  800 ,
                "height":  600 
            },"genre": "posts","keywords": "Mybatis, 源码","wordcount":  5256 ,
        "url": "http:\/\/example.org\/mybatis%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90%E4%B8%89-%E5%8A%A0%E8%BD%BDmybatis-config.xml%E5%86%85%E5%AE%B9\/","datePublished": "2020-04-26","dateModified": "2020-04-26","publisher": {
                "@type": "Organization",
                "name": "Janyd",
                "logo": {
                "@type": "ImageObject",
                "url": "http:\/\/example.org\/logo.png",
                "width":  127 ,
                "height":  40 
                }
            },"author": {
                "@type": "Person",
                "name": "Janyd"
            },"description": ""
    }
    </script></head>
    <body><script>
            if (!window.localStorage || !window.localStorage.getItem('theme')) {window.isDark = 'dark' === 'dark';} else {
                window.isDark = (window.localStorage && window.localStorage.getItem('theme')) === 'dark';
            }
            window.isDark && document.body.classList.add('dark-theme');
        </script><div class="wrapper"><header class="desktop" id="header-desktop">
    <div class="header-wrapper">
        <div class="header-title">
            <a href="/">Janyd Blog</a>
        </div>
        <div class="menu"><a class="menu-item" href="/posts/" rel="noopener noreffer">文章</a><a class="menu-item" href="/tags/" rel="noopener noreffer">标签</a><a class="menu-item" href="/categories/" rel="noopener noreffer">分类</a><span class="menu-item">|</span>
            <a href="javascript:void(0);" class="menu-item theme-switch" title="切换主题">
                <i class="fas fa-adjust fa-fw"></i>
            </a></div>
    </div>
</header><header class="mobile" id="header-mobile">
    <div class="header-wrapper">
        <div class="header-container">
            <div class="header-title">
                <a href="/">Janyd Blog</a>
            </div>
            <div class="menu-toggle" id="menu-toggle-mobile">
                <span></span><span></span><span></span>
            </div>
        </div>
        <div class="menu" id="menu-mobile"><a class="menu-item" href="/posts/" title="" rel="noopener noreffer">文章</a><a class="menu-item" href="/tags/" title="" rel="noopener noreffer">标签</a><a class="menu-item" href="/categories/" title="" rel="noopener noreffer">分类</a><a href="javascript:void(0);" class="menu-item theme-switch" title="切换主题">
                <i class="fas fa-adjust fa-fw"></i>
            </a></div>
    </div>
</header>

<script>
    window.desktopHeaderMode = "fixed";
    window.mobileHeaderMode = "auto";
</script>
<main class="main">
                <div class="container"><article class="page single"><h1 class="single-title animated flipInX">Mybatis加载流程分析(三) - 加载mybatis-config.xml内容</h1><div class="post-meta">
            <div class="post-meta-line"><span class="post-author"><a href="https://github.com/Janyd" title="Author" target="_blank" rel="noopener noreffer author" class="author"><i class="fas fa-user-circle fa-fw"></i>Janyd</a>
</span>&nbsp;
                    <span class="post-category">收录于<a href="/categories/mybatis%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90">
                                <i class="far fa-folder fa-fw"></i>Mybatis源码解析
                            </a></span></div>
            <div class="post-meta-line"><i class="far fa-calendar-alt fa-fw"></i><time datetime=2020-04-26>2020-04-26</time>&nbsp;
                <i class="fas fa-pencil-alt fa-fw"></i>约 5256 字&nbsp;
                <i class="far fa-clock fa-fw"></i>预计阅读 11 分钟&nbsp;</div>
        </div><div class="toc" id="toc-auto">
                <h2 class="toc-title">目录</h2>
                <div class="toc-content" id="toc-content-auto"></div>
            </div>
            <div class="toc" id="toc-static">
                <details>
                    <summary>
                        <div class="toc-title">
                            <span>目录</span>
                            <span><i class="details icon fas fa-angle-down"></i></span>
                        </div>
                    </summary>
                    <div class="toc-content" id="toc-content-static"><nav id="TableOfContents">
  <ul>
    <li><a href="#动态配置加载propertieselement">动态配置加载propertiesElement</a></li>
    <li><a href="#settings节点解析settingsasproperties">settings节点解析settingsAsProperties</a></li>
    <li><a href="#加载类型别名typealiaseselement">加载类型别名typeAliasesElement</a></li>
    <li><a href="#加载插件pluginelement">加载插件pluginElement</a></li>
    <li><a href="#加载对象工厂">加载对象工厂</a></li>
    <li><a href="#加载对象包装工厂objectwrapperfactoryelement">加载对象包装工厂objectWrapperFactoryElement</a></li>
    <li><a href="#加载反射器工厂reflectorfactoryelement">加载反射器工厂reflectorFactoryElement</a></li>
    <li><a href="#加载环境">加载环境</a></li>
    <li><a href="#加载类型映射typehandlerelement">加载类型映射typeHandlerElement</a></li>
    <li><a href="#总结">总结</a></li>
    <li><a href="#参考链接">参考链接</a></li>
  </ul>
</nav></div>
                </details>
            </div><div class="content" id="content"><h2 id="动态配置加载propertieselement">动态配置加载propertiesElement</h2>
<p>Mybatis中的动态配置指的是上篇${}占位符替换，而这些变量来自于<code>mybatis-config.xml</code>中节点<code>&lt;properties /&gt;</code>，或者从<code>XMLConfigBuilder</code>构造函数传入<code>prop</code>，<code>mybatis-config.xml</code>节点<code>&lt;properties /&gt;</code>也有两种方式：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-xml" data-lang="xml"><span class="nt">&lt;properties</span> <span class="na">resource=</span><span class="s">&#34;org/apache/ibatis/databases/blog/blog-derby.properties&#34;</span><span class="nt">&gt;</span> //properties文件地址
    <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;username&#34;</span> <span class="na">value=</span><span class="s">&#34;username&#34;</span><span class="nt">/&gt;</span> 在properties节点里设置属性值
    <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;password&#34;</span> <span class="na">value=</span><span class="s">&#34;password&#34;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/properties&gt;</span>
</code></pre></td></tr></table>
</div>
</div><p>而三种种方式优先级是：
<div class="mermaid" id="id-93d3ce"></div>
优先级越低就有可能相同变量名就会被优先级越高的覆盖，我们可以看<code>XMLConfigBuilder#propertiesElement</code>源码</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="kd">private</span> <span class="kt">void</span> <span class="nf">propertiesElement</span><span class="o">(</span><span class="n">XNode</span> <span class="n">context</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">context</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">//先读取子节点变量
</span><span class="c1"></span>        <span class="n">Properties</span> <span class="n">defaults</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getChildrenAsProperties</span><span class="o">();</span>
        <span class="n">String</span> <span class="n">resource</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;resource&#34;</span><span class="o">);</span>
        <span class="n">String</span> <span class="n">url</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;url&#34;</span><span class="o">);</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">resource</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&amp;&amp;</span> <span class="n">url</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>

            <span class="k">throw</span> <span class="k">new</span> <span class="n">BuilderException</span><span class="o">(</span><span class="s">&#34;The properties element cannot specify both a URL and a resource based property file reference.  Please specify one or the other.&#34;</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="c1">//后加载properties文件，并且添加到default，如有相同键名就会被覆盖
</span><span class="c1"></span>        <span class="k">if</span> <span class="o">(</span><span class="n">resource</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">defaults</span><span class="o">.</span><span class="na">putAll</span><span class="o">(</span><span class="n">Resources</span><span class="o">.</span><span class="na">getResourceAsProperties</span><span class="o">(</span><span class="n">resource</span><span class="o">));</span>
        <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">url</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">defaults</span><span class="o">.</span><span class="na">putAll</span><span class="o">(</span><span class="n">Resources</span><span class="o">.</span><span class="na">getUrlAsProperties</span><span class="o">(</span><span class="n">url</span><span class="o">));</span>
        <span class="o">}</span>
        <span class="c1">//取出先前构造函数传入的变量，然后添加进default，如有相同键名会将构造函数传入的变量覆盖于上面两个方式的变量
</span><span class="c1"></span>        <span class="n">Properties</span> <span class="n">vars</span> <span class="o">=</span> <span class="n">configuration</span><span class="o">.</span><span class="na">getVariables</span><span class="o">();</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">vars</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">defaults</span><span class="o">.</span><span class="na">putAll</span><span class="o">(</span><span class="n">vars</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="n">parser</span><span class="o">.</span><span class="na">setVariables</span><span class="o">(</span><span class="n">defaults</span><span class="o">);</span>
        <span class="n">configuration</span><span class="o">.</span><span class="na">setVariables</span><span class="o">(</span><span class="n">defaults</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><p>这里还有个点就是<code>url</code> 或 <code>resource</code>不能同时配置，<code>resource</code>其实就是本地文件地址，而<code>url</code>统一资源定位符，这个可以指定一个网址只要他返回properties文件内容即可</p>
<h2 id="settings节点解析settingsasproperties">settings节点解析settingsAsProperties</h2>
<blockquote>
</blockquote>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="cm">/**
</span><span class="cm">    * 解析settings节点的配置信息，并且校验Configuration是否存在该字段
</span><span class="cm">    *
</span><span class="cm">    * @param context
</span><span class="cm">    * @return
</span><span class="cm">    */</span>
<span class="kd">private</span> <span class="n">Properties</span> <span class="nf">settingsAsProperties</span><span class="o">(</span><span class="n">XNode</span> <span class="n">context</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">context</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="k">new</span> <span class="n">Properties</span><span class="o">();</span>
    <span class="o">}</span>
    <span class="n">Properties</span> <span class="n">props</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getChildrenAsProperties</span><span class="o">();</span>
    <span class="c1">// Check that all settings are known to the configuration class
</span><span class="c1"></span>    <span class="n">MetaClass</span> <span class="n">metaConfig</span> <span class="o">=</span> <span class="n">MetaClass</span><span class="o">.</span><span class="na">forClass</span><span class="o">(</span><span class="n">Configuration</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">localReflectorFactory</span><span class="o">);</span>
    <span class="k">for</span> <span class="o">(</span><span class="n">Object</span> <span class="n">key</span> <span class="o">:</span> <span class="n">props</span><span class="o">.</span><span class="na">keySet</span><span class="o">())</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(!</span><span class="n">metaConfig</span><span class="o">.</span><span class="na">hasSetter</span><span class="o">(</span><span class="n">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="n">key</span><span class="o">)))</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="n">BuilderException</span><span class="o">(</span><span class="s">&#34;The setting &#34;</span> <span class="o">+</span> <span class="n">key</span> <span class="o">+</span> <span class="s">&#34; is not known.  Make sure you spelled it correctly (case sensitive).&#34;</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="n">props</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><p>settings解析很简单，解析的内容主要是<code>Configuration</code>配置项，完整配置如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-xml" data-lang="xml"><span class="nt">&lt;settings&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;cacheEnabled&#34;</span> <span class="na">value=</span><span class="s">&#34;true&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;lazyLoadingEnabled&#34;</span> <span class="na">value=</span><span class="s">&#34;true&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;multipleResultSetsEnabled&#34;</span> <span class="na">value=</span><span class="s">&#34;true&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;useColumnLabel&#34;</span> <span class="na">value=</span><span class="s">&#34;true&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;useGeneratedKeys&#34;</span> <span class="na">value=</span><span class="s">&#34;false&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;autoMappingBehavior&#34;</span> <span class="na">value=</span><span class="s">&#34;PARTIAL&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;autoMappingUnknownColumnBehavior&#34;</span> <span class="na">value=</span><span class="s">&#34;WARNING&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;defaultExecutorType&#34;</span> <span class="na">value=</span><span class="s">&#34;SIMPLE&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;defaultStatementTimeout&#34;</span> <span class="na">value=</span><span class="s">&#34;25&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;defaultFetchSize&#34;</span> <span class="na">value=</span><span class="s">&#34;100&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;safeRowBoundsEnabled&#34;</span> <span class="na">value=</span><span class="s">&#34;false&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;mapUnderscoreToCamelCase&#34;</span> <span class="na">value=</span><span class="s">&#34;false&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;localCacheScope&#34;</span> <span class="na">value=</span><span class="s">&#34;SESSION&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;jdbcTypeForNull&#34;</span> <span class="na">value=</span><span class="s">&#34;OTHER&#34;</span><span class="nt">/&gt;</span>
  <span class="nt">&lt;setting</span> <span class="na">name=</span><span class="s">&#34;lazyLoadTriggerMethods&#34;</span> <span class="na">value=</span><span class="s">&#34;equals,clone,hashCode,toString&#34;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/settings&gt;</span>
</code></pre></td></tr></table>
</div>
</div><p>具体含义可到<a href="https://mybatis.org/mybatis-3/zh/configuration.html#settings" target="_blank" rel="noopener noreffer">Mybatis官网查看</a>
</p>
<p>这里要说两个就是<code>VFS</code>与<code>Log</code>，<code>Log</code>比较容易理解其实就是Mybatis框架的日志打印，可由用户自行实现也可用Mybatis自带。<code>VFS</code>指的就是VFS（virtual File System）虚拟文件系统，主要用来加载容器内的各种资源，比如jar或class文件。Mybatis内部提供<code>DefaultVFS</code>与<code>JBoss6VFS</code>，<code>VFS</code>有两个抽象方法：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="c1">//是否生效
</span><span class="c1"></span><span class="kd">public</span> <span class="kd">abstract</span> <span class="kt">boolean</span> <span class="nf">isValid</span><span class="o">();</span>
<span class="c1">//递归列出某个文件夹下所有子资源的全路径
</span><span class="c1"></span><span class="kd">protected</span> <span class="kd">abstract</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="nf">list</span><span class="o">(</span><span class="n">URL</span> <span class="n">url</span><span class="o">,</span> <span class="n">String</span> <span class="n">forPath</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span><span class="o">;</span>
</code></pre></td></tr></table>
</div>
</div><p><code>list</code>仅在<code>VFS#list(path)</code>所使用：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="nf">list</span><span class="o">(</span><span class="n">String</span> <span class="n">path</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
    <span class="n">List</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="n">names</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ArrayList</span><span class="o">&lt;&gt;();</span>
    <span class="k">for</span> <span class="o">(</span><span class="n">URL</span> <span class="n">url</span> <span class="o">:</span> <span class="n">getResources</span><span class="o">(</span><span class="n">path</span><span class="o">))</span> <span class="o">{</span>
        <span class="n">names</span><span class="o">.</span><span class="na">addAll</span><span class="o">(</span><span class="n">list</span><span class="o">(</span><span class="n">url</span><span class="o">,</span> <span class="n">path</span><span class="o">));</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="n">names</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><p>而该方法也只会<code>ResolverUtil&lt;T&gt;</code>所使用的，而<code>ResolverUtil&lt;T&gt;</code>的作用为了能够获取某些包名下的<code>.class</code>类文件。<br>
这几类属于<code>org.apache.ibatis.io</code>模块里，属于专门处理io。</p>
<h2 id="加载类型别名typealiaseselement">加载类型别名typeAliasesElement</h2>
<p>何为类型别名？直接看到<code>TypeAliasRegistry</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span><span class="lnt">68
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">TypeAliasRegistry</span> <span class="o">{</span>

    <span class="kd">private</span> <span class="kd">final</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">Class</span><span class="o">&lt;?&gt;&gt;</span> <span class="n">typeAliases</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;&gt;();</span>

    <span class="c1">//构造函数预注册
</span><span class="c1"></span>    <span class="kd">public</span> <span class="nf">TypeAliasRegistry</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;string&#34;</span><span class="o">,</span> <span class="n">String</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>

        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;byte&#34;</span><span class="o">,</span> <span class="n">Byte</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;long&#34;</span><span class="o">,</span> <span class="n">Long</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;short&#34;</span><span class="o">,</span> <span class="n">Short</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;int&#34;</span><span class="o">,</span> <span class="n">Integer</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;integer&#34;</span><span class="o">,</span> <span class="n">Integer</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;double&#34;</span><span class="o">,</span> <span class="n">Double</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;float&#34;</span><span class="o">,</span> <span class="n">Float</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;boolean&#34;</span><span class="o">,</span> <span class="n">Boolean</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>

        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;byte[]&#34;</span><span class="o">,</span> <span class="n">Byte</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;long[]&#34;</span><span class="o">,</span> <span class="n">Long</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;short[]&#34;</span><span class="o">,</span> <span class="n">Short</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;int[]&#34;</span><span class="o">,</span> <span class="n">Integer</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;integer[]&#34;</span><span class="o">,</span> <span class="n">Integer</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;double[]&#34;</span><span class="o">,</span> <span class="n">Double</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;float[]&#34;</span><span class="o">,</span> <span class="n">Float</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;boolean[]&#34;</span><span class="o">,</span> <span class="n">Boolean</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>

        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_byte&#34;</span><span class="o">,</span> <span class="kt">byte</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_long&#34;</span><span class="o">,</span> <span class="kt">long</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_short&#34;</span><span class="o">,</span> <span class="kt">short</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_int&#34;</span><span class="o">,</span> <span class="kt">int</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_integer&#34;</span><span class="o">,</span> <span class="kt">int</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_double&#34;</span><span class="o">,</span> <span class="kt">double</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_float&#34;</span><span class="o">,</span> <span class="kt">float</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_boolean&#34;</span><span class="o">,</span> <span class="kt">boolean</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>

        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_byte[]&#34;</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_long[]&#34;</span><span class="o">,</span> <span class="kt">long</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_short[]&#34;</span><span class="o">,</span> <span class="kt">short</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_int[]&#34;</span><span class="o">,</span> <span class="kt">int</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_integer[]&#34;</span><span class="o">,</span> <span class="kt">int</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_double[]&#34;</span><span class="o">,</span> <span class="kt">double</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_float[]&#34;</span><span class="o">,</span> <span class="kt">float</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;_boolean[]&#34;</span><span class="o">,</span> <span class="kt">boolean</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>

        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;date&#34;</span><span class="o">,</span> <span class="n">Date</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;decimal&#34;</span><span class="o">,</span> <span class="n">BigDecimal</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;bigdecimal&#34;</span><span class="o">,</span> <span class="n">BigDecimal</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;biginteger&#34;</span><span class="o">,</span> <span class="n">BigInteger</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;object&#34;</span><span class="o">,</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>

        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;date[]&#34;</span><span class="o">,</span> <span class="n">Date</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;decimal[]&#34;</span><span class="o">,</span> <span class="n">BigDecimal</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;bigdecimal[]&#34;</span><span class="o">,</span> <span class="n">BigDecimal</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;biginteger[]&#34;</span><span class="o">,</span> <span class="n">BigInteger</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;object[]&#34;</span><span class="o">,</span> <span class="n">Object</span><span class="o">[].</span><span class="na">class</span><span class="o">);</span>

        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;map&#34;</span><span class="o">,</span> <span class="n">Map</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;hashmap&#34;</span><span class="o">,</span> <span class="n">HashMap</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;list&#34;</span><span class="o">,</span> <span class="n">List</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;arraylist&#34;</span><span class="o">,</span> <span class="n">ArrayList</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;collection&#34;</span><span class="o">,</span> <span class="n">Collection</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;iterator&#34;</span><span class="o">,</span> <span class="n">Iterator</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>

        <span class="n">registerAlias</span><span class="o">(</span><span class="s">&#34;ResultSet&#34;</span><span class="o">,</span> <span class="n">ResultSet</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="c1">//先忽略其他方法
</span><span class="c1"></span><span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><p>这个是一个别名类型，意思就是给出一个别名能够使用别名找到该类型，一般用在解析ResultMap中。而在<code>XMLConfigBuilder</code>加载的是用户自定义的别名类型或指定包，一般<code>package</code>会将整个<code>entity</code>都注册进别名类型中，代码如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="cm">/**
</span><span class="cm"> * 加载别名节点配置
</span><span class="cm"> *
</span><span class="cm"> * @param parent
</span><span class="cm"> */</span>
<span class="kd">private</span> <span class="kt">void</span> <span class="nf">typeAliasesElement</span><span class="o">(</span><span class="n">XNode</span> <span class="n">parent</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">parent</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">for</span> <span class="o">(</span><span class="n">XNode</span> <span class="n">child</span> <span class="o">:</span> <span class="n">parent</span><span class="o">.</span><span class="na">getChildren</span><span class="o">())</span> <span class="o">{</span>
            <span class="k">if</span> <span class="o">(</span><span class="s">&#34;package&#34;</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">child</span><span class="o">.</span><span class="na">getName</span><span class="o">()))</span> <span class="o">{</span>
                <span class="n">String</span> <span class="n">typeAliasPackage</span> <span class="o">=</span> <span class="n">child</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;name&#34;</span><span class="o">);</span>
                <span class="n">configuration</span><span class="o">.</span><span class="na">getTypeAliasRegistry</span><span class="o">().</span><span class="na">registerAliases</span><span class="o">(</span><span class="n">typeAliasPackage</span><span class="o">);</span>
            <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
                <span class="n">String</span> <span class="n">alias</span> <span class="o">=</span> <span class="n">child</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;alias&#34;</span><span class="o">);</span>
                <span class="n">String</span> <span class="n">type</span> <span class="o">=</span> <span class="n">child</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;type&#34;</span><span class="o">);</span>
                <span class="k">try</span> <span class="o">{</span>
                    <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">clazz</span> <span class="o">=</span> <span class="n">Resources</span><span class="o">.</span><span class="na">classForName</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
                    <span class="k">if</span> <span class="o">(</span><span class="n">alias</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
                        <span class="n">typeAliasRegistry</span><span class="o">.</span><span class="na">registerAlias</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>
                    <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
                        <span class="n">typeAliasRegistry</span><span class="o">.</span><span class="na">registerAlias</span><span class="o">(</span><span class="n">alias</span><span class="o">,</span> <span class="n">clazz</span><span class="o">);</span>
                    <span class="o">}</span>
                <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">ClassNotFoundException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
                    <span class="k">throw</span> <span class="k">new</span> <span class="n">BuilderException</span><span class="o">(</span><span class="s">&#34;Error registering typeAlias for &#39;&#34;</span> <span class="o">+</span> <span class="n">alias</span> <span class="o">+</span> <span class="s">&#34;&#39;. Cause: &#34;</span> <span class="o">+</span> <span class="n">e</span><span class="o">,</span> <span class="n">e</span><span class="o">);</span>
                <span class="o">}</span>
            <span class="o">}</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><h2 id="加载插件pluginelement">加载插件pluginElement</h2>
<p>Mybatis为用户提供了插件系统，能允许用户在映射语句执行过程进行拦截调用，更改Mybatis的默认行为例如修改SQL等等，以下是Mybatis允许用户使用插件进行拦截接口方法：</p>
<ul>
<li>org.apache.ibatis.executor.Executor(update、query、queryCursor、flushStatements、commit、rollback、close、isClosed)</li>
<li>org.apache.ibatis.executor.statement.StatementHandler(prepare、batch、update、query)</li>
<li>org.apache.ibatis.executor.parameter.ParameterHandler(getParameterObject、setParameters)</li>
<li>org.apache.ibatis.executor.resultset.ResultSetHandler(handleResultSets、handleCursorResultSets、handleOutputParameters)
Mybatis提供了<code>org.apache.ibatis.plugin.Interceptor</code>接口来实现插件，但实现接口还不行，还需要加上注解<code>org.apache.ibatis.plugin.Intercepts</code>与<code>org/apache/ibatis/plugin/Signature</code>，<code>Intercepts</code>主要是包含多个<code>Signature</code>，重点在于<code>Signature</code>属性：</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="cm">/**
</span><span class="cm"> * The annotation that indicate the method signature.
</span><span class="cm"> *
</span><span class="cm"> * @see Intercepts
</span><span class="cm"> * @author Clinton Begin
</span><span class="cm"> */</span>
<span class="nd">@Documented</span>
<span class="nd">@Retention</span><span class="o">(</span><span class="n">RetentionPolicy</span><span class="o">.</span><span class="na">RUNTIME</span><span class="o">)</span>
<span class="nd">@Target</span><span class="o">({})</span>
<span class="kd">public</span> <span class="nd">@interface</span> <span class="n">Signature</span> <span class="o">{</span>
    <span class="cm">/**
</span><span class="cm">     * 指定四大金刚：Executor、StatementHandler、ParameterHandler、ResultSetHandler
</span><span class="cm">     * Returns the java type.
</span><span class="cm">     *
</span><span class="cm">     * @return the java type
</span><span class="cm">     */</span>
    <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">type</span><span class="o">();</span>

    <span class="cm">/**
</span><span class="cm">     * 指定上面接口中的方法
</span><span class="cm">     * Returns the method name.
</span><span class="cm">     *
</span><span class="cm">     * @return the method name
</span><span class="cm">     */</span>
    <span class="n">String</span> <span class="nf">method</span><span class="o">();</span>

    <span class="cm">/**
</span><span class="cm">     * 指定上面方法的参数类型，并必须
</span><span class="cm">     * Returns java types for method argument.
</span><span class="cm">     * @return java types for method argument
</span><span class="cm">     */</span>
    <span class="n">Class</span><span class="o">&lt;?&gt;[]</span> <span class="n">args</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><p>现在最常见的插件就是分页插件，例如<code>PageHelper</code>(<a href="https://github.com/pagehelper/Mybatis-PageHelper" target="_blank" rel="noopener noreffer">Github坐标</a>
)。</p>
<h2 id="加载对象工厂">加载对象工厂</h2>
<p>在Mybatis里对象工厂的作用就是实例化，并且支持有构造函数，同时支持集合类(List、Map等等)的创建，主要是Mybatis中有结果集映射，需要返回相应的类型，有时候多个结果时那肯定是需要集合的，所以需要一个对象工厂来帮忙实例化并设置值，Mybatis已经提供一个默认的<code>DefaultObjectFactory</code>，加载过程如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="cm">/**
</span><span class="cm"> * 加载自定义对象工厂实现类
</span><span class="cm"> * &lt;objectFactory type=&#34;org.mybatis.example.ExampleObjectFactory&#34;&gt;
</span><span class="cm"> * &lt;property name=&#34;someProperty&#34; value=&#34;100&#34;/&gt;
</span><span class="cm"> * &lt;/objectFactory&gt;
</span><span class="cm"> *
</span><span class="cm"> * @param context
</span><span class="cm"> * @throws Exception
</span><span class="cm"> */</span>
<span class="kd">private</span> <span class="kt">void</span> <span class="nf">objectFactoryElement</span><span class="o">(</span><span class="n">XNode</span> <span class="n">context</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">context</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">String</span> <span class="n">type</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;type&#34;</span><span class="o">);</span>
        <span class="n">Properties</span> <span class="n">properties</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getChildrenAsProperties</span><span class="o">();</span>
        <span class="n">ObjectFactory</span> <span class="n">factory</span> <span class="o">=</span> <span class="o">(</span><span class="n">ObjectFactory</span><span class="o">)</span> <span class="n">resolveClass</span><span class="o">(</span><span class="n">type</span><span class="o">).</span><span class="na">getDeclaredConstructor</span><span class="o">().</span><span class="na">newInstance</span><span class="o">();</span>
        <span class="n">factory</span><span class="o">.</span><span class="na">setProperties</span><span class="o">(</span><span class="n">properties</span><span class="o">);</span>
        <span class="n">configuration</span><span class="o">.</span><span class="na">setObjectFactory</span><span class="o">(</span><span class="n">factory</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><h2 id="加载对象包装工厂objectwrapperfactoryelement">加载对象包装工厂objectWrapperFactoryElement</h2>
<p>此处加载用户定义的<code>ObjectWrapperFactory</code>的实现类，系统也提供了<code>DefaultObjectWrapperFactory</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="cm">/**
</span><span class="cm"> * @author Clinton Begin
</span><span class="cm"> */</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">DefaultObjectWrapperFactory</span> <span class="kd">implements</span> <span class="n">ObjectWrapperFactory</span> <span class="o">{</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">hasWrapperFor</span><span class="o">(</span><span class="n">Object</span> <span class="n">object</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">ObjectWrapper</span> <span class="nf">getWrapperFor</span><span class="o">(</span><span class="n">MetaObject</span> <span class="n">metaObject</span><span class="o">,</span> <span class="n">Object</span> <span class="n">object</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="n">ReflectionException</span><span class="o">(</span><span class="s">&#34;The DefaultObjectWrapperFactory should never be called to provide an ObjectWrapper.&#34;</span><span class="o">);</span>
    <span class="o">}</span>

<span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><p>从代码看来是个不实现任何内容的空类，Mybaits默认不实现该类，而查看方法引用只有在<code>org.apache.ibatis.reflection.MetaObject</code>的构造函数引用：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MetaObject</span> <span class="o">{</span>

    <span class="c1">//原对象
</span><span class="c1"></span>    <span class="kd">private</span> <span class="kd">final</span> <span class="n">Object</span> <span class="n">originalObject</span><span class="o">;</span>
    <span class="c1">//对象封装
</span><span class="c1"></span>    <span class="kd">private</span> <span class="kd">final</span> <span class="n">ObjectWrapper</span> <span class="n">objectWrapper</span><span class="o">;</span>
    <span class="c1">//对象工厂
</span><span class="c1"></span>    <span class="kd">private</span> <span class="kd">final</span> <span class="n">ObjectFactory</span> <span class="n">objectFactory</span><span class="o">;</span>
    <span class="c1">//对象工厂
</span><span class="c1"></span>    <span class="kd">private</span> <span class="kd">final</span> <span class="n">ObjectWrapperFactory</span> <span class="n">objectWrapperFactory</span><span class="o">;</span>
    <span class="c1">//反射器工厂
</span><span class="c1"></span>    <span class="kd">private</span> <span class="kd">final</span> <span class="n">ReflectorFactory</span> <span class="n">reflectorFactory</span><span class="o">;</span>

    <span class="kd">private</span> <span class="nf">MetaObject</span><span class="o">(</span><span class="n">Object</span> <span class="n">object</span><span class="o">,</span> <span class="n">ObjectFactory</span> <span class="n">objectFactory</span><span class="o">,</span> <span class="n">ObjectWrapperFactory</span> <span class="n">objectWrapperFactory</span><span class="o">,</span> <span class="n">ReflectorFactory</span> <span class="n">reflectorFactory</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">originalObject</span> <span class="o">=</span> <span class="n">object</span><span class="o">;</span>
        <span class="k">this</span><span class="o">.</span><span class="na">objectFactory</span> <span class="o">=</span> <span class="n">objectFactory</span><span class="o">;</span>
        <span class="k">this</span><span class="o">.</span><span class="na">objectWrapperFactory</span> <span class="o">=</span> <span class="n">objectWrapperFactory</span><span class="o">;</span>
        <span class="k">this</span><span class="o">.</span><span class="na">reflectorFactory</span> <span class="o">=</span> <span class="n">reflectorFactory</span><span class="o">;</span>

        <span class="k">if</span> <span class="o">(</span><span class="n">object</span> <span class="k">instanceof</span> <span class="n">ObjectWrapper</span><span class="o">)</span> <span class="o">{</span>

            <span class="k">this</span><span class="o">.</span><span class="na">objectWrapper</span> <span class="o">=</span> <span class="o">(</span><span class="n">ObjectWrapper</span><span class="o">)</span> <span class="n">object</span><span class="o">;</span>
        <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">objectWrapperFactory</span><span class="o">.</span><span class="na">hasWrapperFor</span><span class="o">(</span><span class="n">object</span><span class="o">))</span> <span class="o">{</span>
            <span class="c1">//此处使用到了对象包装工厂
</span><span class="c1"></span>            <span class="k">this</span><span class="o">.</span><span class="na">objectWrapper</span> <span class="o">=</span> <span class="n">objectWrapperFactory</span><span class="o">.</span><span class="na">getWrapperFor</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">object</span><span class="o">);</span>
        <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">object</span> <span class="k">instanceof</span> <span class="n">Map</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">this</span><span class="o">.</span><span class="na">objectWrapper</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MapWrapper</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="o">(</span><span class="n">Map</span><span class="o">)</span> <span class="n">object</span><span class="o">);</span>
        <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">object</span> <span class="k">instanceof</span> <span class="n">Collection</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">this</span><span class="o">.</span><span class="na">objectWrapper</span> <span class="o">=</span> <span class="k">new</span> <span class="n">CollectionWrapper</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="o">(</span><span class="n">Collection</span><span class="o">)</span> <span class="n">object</span><span class="o">);</span>
        <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
            <span class="k">this</span><span class="o">.</span><span class="na">objectWrapper</span> <span class="o">=</span> <span class="k">new</span> <span class="n">BeanWrapper</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">object</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>

    <span class="c1">//省略
</span><span class="c1"></span><span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><p>而<code>org.apache.ibatis.reflection.wrapper.ObjectWrapper</code>代码如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="cm">/**
</span><span class="cm"> * 对象封装，基于MetaClass
</span><span class="cm"> *
</span><span class="cm"> * @author Clinton Begin
</span><span class="cm"> */</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">ObjectWrapper</span> <span class="o">{</span>

    <span class="n">Object</span> <span class="nf">get</span><span class="o">(</span><span class="n">PropertyTokenizer</span> <span class="n">prop</span><span class="o">);</span>

    <span class="kt">void</span> <span class="nf">set</span><span class="o">(</span><span class="n">PropertyTokenizer</span> <span class="n">prop</span><span class="o">,</span> <span class="n">Object</span> <span class="n">value</span><span class="o">);</span>

    <span class="n">String</span> <span class="nf">findProperty</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">useCamelCaseMapping</span><span class="o">);</span>

    <span class="n">String</span><span class="o">[]</span> <span class="nf">getGetterNames</span><span class="o">();</span>

    <span class="n">String</span><span class="o">[]</span> <span class="nf">getSetterNames</span><span class="o">();</span>

    <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">getSetterType</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">);</span>

    <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">getGetterType</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">);</span>

    <span class="kt">boolean</span> <span class="nf">hasSetter</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">);</span>

    <span class="kt">boolean</span> <span class="nf">hasGetter</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">);</span>

    <span class="n">MetaObject</span> <span class="nf">instantiatePropertyValue</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">PropertyTokenizer</span> <span class="n">prop</span><span class="o">,</span> <span class="n">ObjectFactory</span> <span class="n">objectFactory</span><span class="o">);</span>

    <span class="kt">boolean</span> <span class="nf">isCollection</span><span class="o">();</span>

    <span class="kt">void</span> <span class="nf">add</span><span class="o">(</span><span class="n">Object</span> <span class="n">element</span><span class="o">);</span>

    <span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="nf">addAll</span><span class="o">(</span><span class="n">List</span><span class="o">&lt;</span><span class="n">E</span><span class="o">&gt;</span> <span class="n">element</span><span class="o">);</span>

<span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><p>能够清晰的知道对一个对象封装，能够快速对对象getter与setter，<code>org.apache.ibatis.reflection.wrapper.ObjectWrapper</code>有<code>BeanWrapper</code>、<code>MapWrapper</code>、<code>CollectionWrapper</code>实现，当然你可以自己实现。</p>
<h2 id="加载反射器工厂reflectorfactoryelement">加载反射器工厂reflectorFactoryElement</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="kd">private</span> <span class="kt">void</span> <span class="nf">reflectorFactoryElement</span><span class="o">(</span><span class="n">XNode</span> <span class="n">context</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">context</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">String</span> <span class="n">type</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;type&#34;</span><span class="o">);</span>
        <span class="n">ReflectorFactory</span> <span class="n">factory</span> <span class="o">=</span> <span class="o">(</span><span class="n">ReflectorFactory</span><span class="o">)</span> <span class="n">resolveClass</span><span class="o">(</span><span class="n">type</span><span class="o">).</span><span class="na">getDeclaredConstructor</span><span class="o">().</span><span class="na">newInstance</span><span class="o">();</span>
        <span class="n">configuration</span><span class="o">.</span><span class="na">setReflectorFactory</span><span class="o">(</span><span class="n">factory</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><p>加载用户自定义的<code>ReflectorFactory</code>反射器工厂，如果没有Mybaits提供了默认实现类<code>DefaultReflectorFactory</code>，该接口的作用是能够获取得到<code>Reflector</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span><span class="lnt">68
</span><span class="lnt">69
</span><span class="lnt">70
</span><span class="lnt">71
</span><span class="lnt">72
</span><span class="lnt">73
</span><span class="lnt">74
</span><span class="lnt">75
</span><span class="lnt">76
</span><span class="lnt">77
</span><span class="lnt">78
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Reflector</span> <span class="o">{</span>

    <span class="cm">/**
</span><span class="cm">     * 反射的Class类型
</span><span class="cm">     */</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">type</span><span class="o">;</span>

    <span class="cm">/**
</span><span class="cm">     * 可通过getter读取的字段数组
</span><span class="cm">     */</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="n">String</span><span class="o">[]</span> <span class="n">readablePropertyNames</span><span class="o">;</span>

    <span class="cm">/**
</span><span class="cm">     * 可通过setter写入的字段数组
</span><span class="cm">     */</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="n">String</span><span class="o">[]</span> <span class="n">writablePropertyNames</span><span class="o">;</span>

    <span class="cm">/**
</span><span class="cm">     * setter方法Method并封装在Invoker内，方便于执行setter方法，key -&gt;字段名称 value -&gt; set的 Invoker
</span><span class="cm">     */</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">Invoker</span><span class="o">&gt;</span> <span class="n">setMethods</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;&gt;();</span>

    <span class="cm">/**
</span><span class="cm">     * getter方法Method方法封装在Invoker内，方便于执行getter方法，key-&gt;字段名称 value-&gt; get的 Invoker
</span><span class="cm">     */</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">Invoker</span><span class="o">&gt;</span> <span class="n">getMethods</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;&gt;();</span>

    <span class="cm">/**
</span><span class="cm">     * setter方法，入参类型
</span><span class="cm">     */</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">Class</span><span class="o">&lt;?&gt;&gt;</span> <span class="n">setTypes</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;&gt;();</span>

    <span class="cm">/**
</span><span class="cm">     * getter方法，出参类型
</span><span class="cm">     */</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">Class</span><span class="o">&lt;?&gt;&gt;</span> <span class="n">getTypes</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;&gt;();</span>

    <span class="cm">/**
</span><span class="cm">     * Class 默认构造函数 ，一般为无参数构造函数
</span><span class="cm">     */</span>
    <span class="kd">private</span> <span class="n">Constructor</span><span class="o">&lt;?&gt;</span> <span class="n">defaultConstructor</span><span class="o">;</span>

    <span class="cm">/**
</span><span class="cm">     * 字段大小写转换，大写字段名key -&gt; 小写字段名value
</span><span class="cm">     */</span>
    <span class="kd">private</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">String</span><span class="o">&gt;</span> <span class="n">caseInsensitivePropertyMap</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;&gt;();</span>

    <span class="kd">public</span> <span class="nf">Reflector</span><span class="o">(</span><span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">clazz</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">//反射器处理的Class
</span><span class="c1"></span>        <span class="n">type</span> <span class="o">=</span> <span class="n">clazz</span><span class="o">;</span>

        <span class="c1">//添加默认构造函数Method
</span><span class="c1"></span>        <span class="n">addDefaultConstructor</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>

        <span class="c1">//查找并添加getter方法
</span><span class="c1"></span>        <span class="n">addGetMethods</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>

        <span class="c1">//查找并添加setter方法
</span><span class="c1"></span>        <span class="n">addSetMethods</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>

        <span class="c1">//查找Class的字段
</span><span class="c1"></span>        <span class="n">addFields</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>

        <span class="c1">//获取可通过getter字段名
</span><span class="c1"></span>        <span class="n">readablePropertyNames</span> <span class="o">=</span> <span class="n">getMethods</span><span class="o">.</span><span class="na">keySet</span><span class="o">().</span><span class="na">toArray</span><span class="o">(</span><span class="k">new</span> <span class="n">String</span><span class="o">[</span><span class="n">0</span><span class="o">]);</span>
        <span class="c1">//获取可通过setter的字段名
</span><span class="c1"></span>        <span class="n">writablePropertyNames</span> <span class="o">=</span> <span class="n">setMethods</span><span class="o">.</span><span class="na">keySet</span><span class="o">().</span><span class="na">toArray</span><span class="o">(</span><span class="k">new</span> <span class="n">String</span><span class="o">[</span><span class="n">0</span><span class="o">]);</span>


        <span class="k">for</span> <span class="o">(</span><span class="n">String</span> <span class="n">propName</span> <span class="o">:</span> <span class="n">readablePropertyNames</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">caseInsensitivePropertyMap</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">propName</span><span class="o">.</span><span class="na">toUpperCase</span><span class="o">(</span><span class="n">Locale</span><span class="o">.</span><span class="na">ENGLISH</span><span class="o">),</span> <span class="n">propName</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="k">for</span> <span class="o">(</span><span class="n">String</span> <span class="n">propName</span> <span class="o">:</span> <span class="n">writablePropertyNames</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">caseInsensitivePropertyMap</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">propName</span><span class="o">.</span><span class="na">toUpperCase</span><span class="o">(</span><span class="n">Locale</span><span class="o">.</span><span class="na">ENGLISH</span><span class="o">),</span> <span class="n">propName</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>
    <span class="c1">//省略
</span><span class="c1"></span><span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><p>从代码可看出是存储了<code>Class</code>的元信息，并且哪些属性是可getter、setter以及相应的方法，就算属性没有getter、setter也可以设置可访问性，强制给对象设置值。</p>
<h2 id="加载环境">加载环境</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="cm">/**
</span><span class="cm"> * 加载环境，用于不同环境不同配置
</span><span class="cm"> *
</span><span class="cm"> * @param context
</span><span class="cm"> * @throws Exception
</span><span class="cm"> */</span>
<span class="kd">private</span> <span class="kt">void</span> <span class="nf">environmentsElement</span><span class="o">(</span><span class="n">XNode</span> <span class="n">context</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">context</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">environment</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">environment</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;default&#34;</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="k">for</span> <span class="o">(</span><span class="n">XNode</span> <span class="n">child</span> <span class="o">:</span> <span class="n">context</span><span class="o">.</span><span class="na">getChildren</span><span class="o">())</span> <span class="o">{</span>
            <span class="n">String</span> <span class="n">id</span> <span class="o">=</span> <span class="n">child</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;id&#34;</span><span class="o">);</span>
            <span class="k">if</span> <span class="o">(</span><span class="n">isSpecifiedEnvironment</span><span class="o">(</span><span class="n">id</span><span class="o">))</span> <span class="o">{</span>
                <span class="n">TransactionFactory</span> <span class="n">txFactory</span> <span class="o">=</span> <span class="n">transactionManagerElement</span><span class="o">(</span><span class="n">child</span><span class="o">.</span><span class="na">evalNode</span><span class="o">(</span><span class="s">&#34;transactionManager&#34;</span><span class="o">));</span>
                <span class="n">DataSourceFactory</span> <span class="n">dsFactory</span> <span class="o">=</span> <span class="n">dataSourceElement</span><span class="o">(</span><span class="n">child</span><span class="o">.</span><span class="na">evalNode</span><span class="o">(</span><span class="s">&#34;dataSource&#34;</span><span class="o">));</span>
                <span class="n">DataSource</span> <span class="n">dataSource</span> <span class="o">=</span> <span class="n">dsFactory</span><span class="o">.</span><span class="na">getDataSource</span><span class="o">();</span>
                <span class="n">Environment</span><span class="o">.</span><span class="na">Builder</span> <span class="n">environmentBuilder</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Environment</span><span class="o">.</span><span class="na">Builder</span><span class="o">(</span><span class="n">id</span><span class="o">)</span>
                    <span class="o">.</span><span class="na">transactionFactory</span><span class="o">(</span><span class="n">txFactory</span><span class="o">)</span>
                    <span class="o">.</span><span class="na">dataSource</span><span class="o">(</span><span class="n">dataSource</span><span class="o">);</span>
                <span class="n">configuration</span><span class="o">.</span><span class="na">setEnvironment</span><span class="o">(</span><span class="n">environmentBuilder</span><span class="o">.</span><span class="na">build</span><span class="o">());</span>
            <span class="o">}</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><p>加载环境主要是要加载数据源信息与选择事务管理器实现类，这里的环境是可以配置多个的，然后选择一个默认，在加载过程就会选择默认那个环境进行初始化，配置如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-xml" data-lang="xml"><span class="nt">&lt;environments</span> <span class="na">default=</span><span class="s">&#34;development&#34;</span><span class="nt">&gt;</span>
  <span class="nt">&lt;environment</span> <span class="na">id=</span><span class="s">&#34;development&#34;</span><span class="nt">&gt;</span>
    <span class="nt">&lt;transactionManager</span> <span class="na">type=</span><span class="s">&#34;JDBC&#34;</span><span class="nt">&gt;</span>
      <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;...&#34;</span> <span class="na">value=</span><span class="s">&#34;...&#34;</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;/transactionManager&gt;</span>
    <span class="nt">&lt;dataSource</span> <span class="na">type=</span><span class="s">&#34;POOLED&#34;</span><span class="nt">&gt;</span>
      <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;driver&#34;</span> <span class="na">value=</span><span class="s">&#34;${driver}&#34;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;url&#34;</span> <span class="na">value=</span><span class="s">&#34;${url}&#34;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;username&#34;</span> <span class="na">value=</span><span class="s">&#34;${username}&#34;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;password&#34;</span> <span class="na">value=</span><span class="s">&#34;${password}&#34;</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;/dataSource&gt;</span>
  <span class="nt">&lt;/environment&gt;&lt;environment</span> <span class="na">id=</span><span class="s">&#34;test&#34;</span><span class="nt">&gt;</span>
    <span class="nt">&lt;transactionManager</span> <span class="na">type=</span><span class="s">&#34;JDBC&#34;</span><span class="nt">&gt;</span>
      <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;...&#34;</span> <span class="na">value=</span><span class="s">&#34;...&#34;</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;/transactionManager&gt;</span>
    <span class="nt">&lt;dataSource</span> <span class="na">type=</span><span class="s">&#34;POOLED&#34;</span><span class="nt">&gt;</span>
      <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;driver&#34;</span> <span class="na">value=</span><span class="s">&#34;${driver}&#34;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;url&#34;</span> <span class="na">value=</span><span class="s">&#34;${url}&#34;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;username&#34;</span> <span class="na">value=</span><span class="s">&#34;${username}&#34;</span><span class="nt">/&gt;</span>
      <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&#34;password&#34;</span> <span class="na">value=</span><span class="s">&#34;${password}&#34;</span><span class="nt">/&gt;</span>
    <span class="nt">&lt;/dataSource&gt;</span>
  <span class="nt">&lt;/environment&gt;</span>
<span class="nt">&lt;/environments&gt;</span>
</code></pre></td></tr></table>
</div>
</div><h2 id="加载类型映射typehandlerelement">加载类型映射typeHandlerElement</h2>
<p>有时候我们遇到entity中有个属性是个复杂对象，对应着数据库应该一个字段，这个时候我们可以使用<code>TypeHandler</code>来进行映射，所以有了自定义类型映射：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="cm">/**
</span><span class="cm"> * 加载用户自定义TypeHandler
</span><span class="cm"> *
</span><span class="cm"> * @param parent
</span><span class="cm"> */</span>
<span class="kd">private</span> <span class="kt">void</span> <span class="nf">typeHandlerElement</span><span class="o">(</span><span class="n">XNode</span> <span class="n">parent</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">parent</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">for</span> <span class="o">(</span><span class="n">XNode</span> <span class="n">child</span> <span class="o">:</span> <span class="n">parent</span><span class="o">.</span><span class="na">getChildren</span><span class="o">())</span> <span class="o">{</span>
            <span class="k">if</span> <span class="o">(</span><span class="s">&#34;package&#34;</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">child</span><span class="o">.</span><span class="na">getName</span><span class="o">()))</span> <span class="o">{</span>
                <span class="n">String</span> <span class="n">typeHandlerPackage</span> <span class="o">=</span> <span class="n">child</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;name&#34;</span><span class="o">);</span>
                <span class="n">typeHandlerRegistry</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="n">typeHandlerPackage</span><span class="o">);</span>
            <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
                <span class="n">String</span> <span class="n">javaTypeName</span> <span class="o">=</span> <span class="n">child</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;javaType&#34;</span><span class="o">);</span>
                <span class="n">String</span> <span class="n">jdbcTypeName</span> <span class="o">=</span> <span class="n">child</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;jdbcType&#34;</span><span class="o">);</span>
                <span class="n">String</span> <span class="n">handlerTypeName</span> <span class="o">=</span> <span class="n">child</span><span class="o">.</span><span class="na">getStringAttribute</span><span class="o">(</span><span class="s">&#34;handler&#34;</span><span class="o">);</span>
                <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">javaTypeClass</span> <span class="o">=</span> <span class="n">resolveClass</span><span class="o">(</span><span class="n">javaTypeName</span><span class="o">);</span>
                <span class="n">JdbcType</span> <span class="n">jdbcType</span> <span class="o">=</span> <span class="n">resolveJdbcType</span><span class="o">(</span><span class="n">jdbcTypeName</span><span class="o">);</span>
                <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">typeHandlerClass</span> <span class="o">=</span> <span class="n">resolveClass</span><span class="o">(</span><span class="n">handlerTypeName</span><span class="o">);</span>
                <span class="k">if</span> <span class="o">(</span><span class="n">javaTypeClass</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
                    <span class="k">if</span> <span class="o">(</span><span class="n">jdbcType</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
                        <span class="n">typeHandlerRegistry</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="n">javaTypeClass</span><span class="o">,</span> <span class="n">typeHandlerClass</span><span class="o">);</span>
                    <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
                        <span class="n">typeHandlerRegistry</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="n">javaTypeClass</span><span class="o">,</span> <span class="n">jdbcType</span><span class="o">,</span> <span class="n">typeHandlerClass</span><span class="o">);</span>
                    <span class="o">}</span>
                <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
                    <span class="n">typeHandlerRegistry</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="n">typeHandlerClass</span><span class="o">);</span>
                <span class="o">}</span>
            <span class="o">}</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></td></tr></table>
</div>
</div><p>所有<code>TypeHandler</code>都需要注册到<code>TypeHandlerRegistry</code>，<code>TypeHandlerRegistry</code>内已经集成了很多基础的<code>TypeHandler</code>，有兴趣的可以看一下。</p>
<h2 id="总结">总结</h2>
<p>本篇文章讲解了部分加载流程内容，讲解了动态配置、VFS资源读取、类型别名、插件、对象工厂、对象包装工厂、反射器工厂、环境配置、类型映射，当然加载流程还没完接下来的才是重要的部分<code>Mapper.xml</code>的解析，也是最复杂的一部分。</p>
<h2 id="参考链接">参考链接</h2>
<ul>
<li><a href="https://mybatis.org/mybatis-3/zh/configuration.html#settings" target="_blank" rel="noopener noreffer">MyBatis 3 | 配置</a>
</li>
<li><a href="https://www.cnblogs.com/zhjh256/p/8512392.html#2.1.3-%E5%8A%A0%E8%BD%BD%E8%87%AA%E5%AE%9A%E4%B9%89vfs-loadcustomvfs" target="_blank" rel="noopener noreffer">加载自定义VFS loadCustomVfs</a>
</li>
<li><a href="https://www.jianshu.com/p/a5ad61aa0973" target="_blank" rel="noopener noreffer">在mybatis配置实体类的别名的两种常用配置方法</a>
</li>
<li><a href="https://www.cnblogs.com/chenpi/p/10498921.html" target="_blank" rel="noopener noreffer">深入理解Mybatis插件开发</a>
</li>
</ul>
</div><div class="post-footer" id="post-footer">
    <div class="post-info">
        <div class="post-info-line">
            <div class="post-info-mod">
                <span>本文于 2020-04-26 更新</span>
            </div>
            <div class="post-info-license"></div>
        </div>
        <div class="post-info-line">
            <div class="post-info-md"><span>
                            <a class="link-to-markdown" href="/mybatis%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90%E4%B8%89-%E5%8A%A0%E8%BD%BDmybatis-config.xml%E5%86%85%E5%AE%B9/index.md" target="_blank">阅读原始文档</a>
                        </span></div>
            <div class="post-info-share">
                <span><a href="javascript:void(0);" title="分享到 微博" data-sharer="weibo" data-url="http://example.org/mybatis%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90%E4%B8%89-%E5%8A%A0%E8%BD%BDmybatis-config.xml%E5%86%85%E5%AE%B9/" data-title="Mybatis加载流程分析(三) - 加载mybatis-config.xml内容"><i class="fab fa-weibo fa-fw"></i></a><a href="javascript:void(0);" title="分享到 Evernote" data-sharer="evernote" data-url="http://example.org/mybatis%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90%E4%B8%89-%E5%8A%A0%E8%BD%BDmybatis-config.xml%E5%86%85%E5%AE%B9/" data-title="Mybatis加载流程分析(三) - 加载mybatis-config.xml内容"><i class="fab fa-evernote fa-fw"></i></a></span>
            </div>
        </div>
    </div>

    <div class="post-info-more">
        <section><i class="fas fa-tags fa-fw"></i>&nbsp;<a href="/tags/mybatis">Mybatis</a>,&nbsp;<a href="/tags/%E6%BA%90%E7%A0%81">源码</a></section>
        <section>
            <span><a href="javascript:window.history.back();">返回</a></span>&nbsp;|&nbsp;<span><a href="/">主页</a></span>
        </section>
    </div>

    <div class="post-nav"><a href="/mybatis%E5%8A%A0%E8%BD%BD%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90%E4%BA%8C-mybatis-config%E8%A7%A3%E6%9E%90/" class="prev" rel="prev" title="Mybatis加载流程分析（二）- mybatis-config解析"><i class="fas fa-angle-left fa-fw"></i>Mybatis加载流程分析（二）- mybatis-config解析</a>
            <a href="/dubbo-%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E4%B8%80-%E9%85%8D%E7%BD%AE/" class="next" rel="next" title="Dubbo 源码分析（一）配置">Dubbo 源码分析（一）配置<i class="fas fa-angle-right fa-fw"></i></a></div>
</div>
<div class="comment"></div>
    </article></div>
            </main><footer class="footer">
    <div class="copyright"><div class="copyright-line">由 <a href="https://gohugo.io/" target="_blank" rel="external nofollow noopener noreffer">Hugo</a> 强力驱动 | 主题 - <a href="https://github.com/dillonzq/LoveIt" target="_blank" rel="external nofollow noopener noreffer"><i class="far fa-heart fa-fw"></i> LoveIt</a>
        </div>

        <div class="copyright-line"><i class="far fa-copyright fa-fw"></i><span itemprop="copyrightYear">2020</span><span class="author" itemprop="copyrightHolder">&nbsp;<a href="https://github.com/Janyd" target="_blank">Janyd</a></span>&nbsp;|&nbsp;<span class="license"><a rel="license external nofollow noopener noreffer" href="https://creativecommons.org/licenses/by-nc/4.0/" target="_blank">CC BY-NC 4.0</a></span></div>
    </div>
</footer>
</div><a href="#" class="dynamic-to-top animated faster" id="dynamic-to-top">
            <i class="fas fa-chevron-up fa-fw"></i>
        </a><script>
        document.addEventListener('DOMContentLoaded', function () {
            lightGallery(document.getElementById('content'), {
                selector: '.lightgallery',
                speed: 400,
                hideBarsDelay: 2000,
                thumbnail: true,
                exThumbImage: 'data-thumbnail',
                thumbWidth: 80,
                thumbContHeight: 80,
            });
        });
    </script><script>
        window.mermaidArr = ["id-93d3ce"];
    </script><script>
        window.contentMap = {"id-93d3ce":"\r\ngraph TD\r\n构造函数prop --\u003e properties文件\r\nproperties文件 --\u003e property节点\r"};
    </script><link rel="stylesheet" href="/lib/lightgallery/lightgallery.min.css"><link rel="stylesheet" href="/lib/mermaid/mermaid.css"><script src="/lib/smooth-scroll/smooth-scroll.polyfills.min.js"></script><script src="/lib/sharer/sharer.min.js"></script><script src="/lib/lazysizes/lazysizes.min.js"></script><script src="/lib/lightgallery/lightgallery.min.js"></script><script src="/lib/lightgallery/lg-thumbnail.min.js"></script><script src="/lib/lightgallery/lg-zoom.min.js"></script><script src="/lib/mermaid/mermaid.min.js"></script><script src="/js/theme.min.js"></script></body>
</html>
